package unrn.isiii.service.ws;

import java.io.Serializable;
import java.util.Collections;
import java.util.HashSet;
import java.util.Set;
import java.util.logging.Level;
import java.util.logging.Logger;

import javax.inject.Singleton;
import javax.websocket.OnClose;
import javax.websocket.OnError;
import javax.websocket.OnMessage;
import javax.websocket.OnOpen;
import javax.websocket.Session;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;

import unrn.isiii.service.ws.Message.MessageDecoder;
import unrn.isiii.service.ws.Message.MessageEncoder;

/**
 * 
 * @author bhalepr
 */
@ServerEndpoint(value = "/linea/{linea}", encoders = { MessageEncoder.class }, decoders = { MessageDecoder.class })
@Singleton
public class LineaEndPoint implements Serializable {

	/**
	 * 
	 */
	private static final long serialVersionUID = -8519619839481355600L;

	private static final Logger logger = Logger
			.getLogger("NotificationEndPoint");

	static Set<Session> sessions = Collections
			.synchronizedSet(new HashSet<Session>());

	
	public static synchronized void sendLinea(Message msg) {
		try {
			for (Session session : sessions) {
				if (session.isOpen()
						&& Boolean.TRUE.equals(session.getUserProperties().get(
								msg.getLinea()))) {
					session.getAsyncRemote().sendObject(msg);
					logger.log(Level.INFO, "Canal Linea - Send: {0}",	msg.getLinea());
					// TODO break;
				}
			}
		} catch (Exception e) {
			logger.log(Level.INFO, "WS Elector Error: {0}", e.toString());
		}
	}

	public static synchronized void sendTodos(Message msg) {
		try {
			logger.log(Level.INFO,
					"Broadcast: cantidad de Sessiones Activas {0}",
					sessions.size());
			for (Session session : sessions) {
				if (session.isOpen()) {
					session.getAsyncRemote().sendObject(msg);
					logger.log(Level.INFO, "Canal Elector - send: {0}",
							msg.toString());
				}
			}
		} catch (Exception e) {
			logger.log(Level.INFO, "WS Elector Error: {0}", e.toString());
		}
	}

	@OnMessage
	public void message(final Session session, Message msg,
			@PathParam("linea") String linea) {
		logger.log(Level.INFO, "Canal Elector - OnReciver:  {0} ",
				msg.toString());
	}

	@OnOpen
	public synchronized void onOpen(Session session,@PathParam("linea") String linea) {
		session.getUserProperties().put(linea, true);
		sessions.add(session);
		logger.log(Level.INFO, "Session-ID : " + session.getId()
				+ " - con Usuario : " + linea + " - Cant.ws.Elector: "
				+ sessions.size());		
	}

	@OnClose
	public void closedConnection(Session session,@PathParam("username") String username) {
		sessions.remove(session);
		logger.log(Level.INFO, "Canal Elector {0}: Connection closed.",
				username);
	}

	@OnError
	public void error(Session session, Throwable t) {
		sessions.remove(session);
		logger.log(Level.INFO, "Canal Elector: Connection error: {0}",
				t.toString());
	}

	public static Set<Session> getSessions() {
		return sessions;
	}

	public static void setSessions(Set<Session> sessions) {
		LineaEndPoint.sessions = sessions;
	}

	public static synchronized void cerrar(String linea) {
		try {
			for (Session session : sessions) {
				if (session.isOpen()
						&& Boolean.TRUE.equals(session.getUserProperties().get(linea))) {
					session.close();
					// break;
				}
			}

		} catch (Exception e) {
			logger.log(Level.INFO, "Error al cerrar canal {0}", e.getMessage());
		}

	}
}
